import { GameMode, world } from "@minecraft/server";
import { Dimensions } from "@sapi-game/constants";
import { RegionProtector, StopWatch } from "@sapi-game/gameComponent";
import { RespawnComponent } from "@sapi-game/gameComponent/player/respawn";
import { SpawnPointProtector } from "@sapi-game/gameComponent/player/spawnProtector";
import { PlayerRegionMonitor } from "@sapi-game/gameComponent/player/regionMonitor";
import { Duration } from "@sapi-game/utils";
import { DirtShopBed } from "../components/bed";
import { DirtShopDaemon } from "../components/daemon";
import { DirtShopMoudle } from "../module";
import { DirtShopPlayer } from "../player";
import { DirtShopEndState } from "./endState";

export class DirtShopMainState extends DirtShopMoudle.State {
    private isEnd = false;

    protected override onEnter(): void {
        this.initPlayers();
        //区域限制
        this.addComponent(PlayerRegionMonitor, {
            region: this.context.map.region,
            onLeave(player) {
                player.player?.kill();
            },
            interval: new Duration(20),
            groups: this.context.groupSet,
        });
        //防止破坏外部方块
        this.addComponent(RegionProtector, {
            region: this.context.map.region,
            blockBreakOutside: true,
            blockInteractOutside: true,
            groupSet: this.context.groupSet,
        });
        //重生点
        this.addComponent(
            SpawnPointProtector,
            {
                playerGroup: this.context.host,
                spawnPoint: this.context.map.hostSpawnPoint,
                dimension: Dimensions.Overworld,
                protectRadius: { x: 0, y: 1, z: 0 },
                protectInterval: new Duration(5),
            },
            "host"
        );
        this.addComponent(
            SpawnPointProtector,
            {
                playerGroup: this.context.attacker,
                spawnPoint: this.context.map.attackerSpawnPoint,
                dimension: Dimensions.Overworld,
                protectRadius: { x: 0, y: 1, z: 0 },
                protectInterval: new Duration(5),
            },
            "attacker"
        );
        //重生组件
        this.addComponent(RespawnComponent<DirtShopPlayer>, {
            groupSet: this.context.groupSet,
            autoBroadcast: true,
            buildNameFunc: (player, group) => {
                return (
                    (group == this.context.host ? "§c[防守]" : "§a[进攻]") +
                    player.name
                );
            },
            onSpawn: (player, group) => {
                if (player.player?.getSpawnPoint() == undefined) {
                    if (group == this.context.host) {
                        player.player?.teleport(
                            this.context.map.hostSpawnPoint
                        );
                    } else {
                        player.player?.teleport(
                            this.context.map.attackerSpawnPoint
                        );
                    }
                }
                player.player?.setGameMode(GameMode.Survival);
                if (!this.context.bedExists && group == this.context.host) {
                    player.player?.setGameMode(GameMode.Spectator);
                    player.title("你死了");
                    player.alive = false;
                }
            },
        });
        this.addComponent(StopWatch, {
            autoStart: true,
            compensate: true,
        });
        this.addComponent(DirtShopDaemon);
        this.addComponent(DirtShopBed);
    }

    initPlayers() {
        world.gameRules.pvp = true;
        this.context.host.forEach((p) => {
            p.player.teleport(this.context.map.hostSpawnPoint);
        });
        this.context.attacker.forEach((p) => {
            p.player.teleport(this.context.map.attackerSpawnPoint);
        });
    }

    end() {
        if (this.isEnd) return;
        const stopWatch = this.getComponent(StopWatch);
        stopWatch.stop();
        this.context.groupSet.title(
            "§a游戏结束",
            `攻破时间:${Math.floor(stopWatch.time / 60)}分${
                stopWatch.time % 60
            }秒`
        );
        this.runner.runDelay((r) => {
            this.transitionTo(DirtShopEndState);
        }, 100);
        this.isEnd = true;
    }
}
